package game.module.mail.logic;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import game.HallServer;
import game.common.ErrorCodeConstants;
import game.entity.PlayingRole;
import game.module.item.bean.GainItemBean;
import game.module.item.logic.ItemManager;
import game.module.mail.bean.HallMailBean;
import game.module.mail.dao.MailCache;
import game.module.mail.dao.MailDao;
import game.module.mail.dao.MailTemplateCache;
import game.module.template.MailTemplate;
import game.module.user.dao.PlayerDao;
import game.session.SessionManager;
import game.util.DateKit;
import game.util.StrKit;
import lion.common.IdWorker;
import lua.LuaMessageHall.MailAttach;
import lua.LuaMessageHall.MailClubInfo;
import lua.LuaMessageHall.MailInfo;
import lua.LuaMessageHall.S2CMailPushList;
import lua.LuaMessageHall.S2CReadMail;

/**
 * @author: Pomelo.Lee
 * @date: 2017年8月24日 下午4:09:52
 */
public class MailManager implements Job {

	private static Logger logger = LoggerFactory.getLogger(MailManager.class);

	private IdWorker uuIdGenerator;

	private static final long DEL_TIME_MIS = 30 * 24 * 3600 * 1000L;

	static class SingletonHolder {
		static MailManager instance = new MailManager();
	}

	public static MailManager getInstance() {
		return SingletonHolder.instance;
	}

	private MailManager() {
		uuIdGenerator = new IdWorker(1);
	}

	/**
	 * 俱乐部加入申请已通过
	 */
	public static final int MAIL_APPLY_AGREE_ID = 2;

	/**
	 * 俱乐部加入申请未通过
	 */
	public static final int MAIL_APPLY_REJECT_ID = 3;
	/**
	 * 捐赠金豆通知
	 */
	public static final int MAIL_DONATE_ID = 4;
	/**
	 * 俱乐部创建成功
	 */
	public static final int MAIL_CREATE_CLUB_ID = 5;

	/**
	 * 俱乐部封赏
	 */
	public static final int MAIL_CLUB_RAISED_ID = 6;

	/**
	 * 信用分调整通知
	 */
	public static final int MAIL_CLUB_CREDIT_ID = 7;

	/**
	 * 俱乐部强制退出通知
	 */
	public static final int MAIL_CLUB_KICK_ID = 8;

	/**
	 * 俱乐部邀请加入通知
	 */
	public static final int MAIL_CLUB_INVITE_ID = 9;

	/**
	 * 俱乐部会长转让通知
	 */
	public static final int MAIL_CLUB_MAKEOVER_ID = 10;

	/**
	 * 俱乐部解散通知
	 */
	public static final int MAIL_CLUB_DISSOLVE_ID = 17;

	/**
	 * 欠账通知
	 */
	public static final int PLAY_DABT = 11;

	/**
	 * 财务通知
	 */
	public static final int FINANCE_INFORM = 12;
	/**
	 * 还账通知
	 */
	public static final int PAY_BACK_INFORM = 13;
	/**
	 * 收账通知
	 */
	public static final int GET_PAY_INFORM = 14;
	/**
	 * 还账通知部分
	 */
	public static final int PAY_PART_INFORM = 15;

	/**
	 * 收账通知部分
	 * 
	 */
	public static final int GET_PART_PAY_INFORM = 16;

	/**
	 * 退出俱乐部通知
	 */
	public static final int CLUB_EXIT_MAIL_ID = 18;

	/**
	 * 发送邮件给所有用户
	 * 
	 * @param toPlayerId
	 * @param templateId
	 * @param sendName
	 * @param title
	 * @param content
	 * @param listMailAttach
	 * @param otherMsg
	 */
	public void sendMailToAllPlayer(int templateId, String sendName, String title, String content, List<GainItemBean> listMailAttach, String otherMsg) {
		List<Integer> playerIds = PlayerDao.getInstance().getAllPlayersIds();
		if (playerIds == null || playerIds.size() <= 0) {
			return;
		}
		HallServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				for (int playerId : playerIds) {
					createMail(playerId, templateId, sendName, title, content, listMailAttach, otherMsg);
				}
			}
		});

	}

	/**
	 * 发送多人邮件异步执行
	 * 
	 * @param playerIds
	 * @param mtid
	 * @param params
	 * @param attach
	 */
	public void asyncendMailToPlayerList(Integer[] playerIds, int mtid, Map<String, String> params, List<GainItemBean> attach) {
		MailTemplate mt = MailTemplateCache.getInstance().getMailTemplateById(mtid);
		if (mt == null || playerIds == null || playerIds.length <= 0) {
			logger.error("sendmail params error!!!");
			return;
		}
		String tempContent = mt.getWords();
		if (params != null && params.size() > 0) {
			for (String key : params.keySet()) {
				tempContent = tempContent.replace(key, params.get(key));
			}
		}
		String content = tempContent;
		String otherMsg = params.get("$OTHER");
		HallServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				for (int playerId : playerIds) {
					createMail(playerId, mtid, "系统邮件", mt.getTitle(), content, attach, otherMsg);
				}
			}
		});

	}

	/**
	 * 发送单个邮件信息
	 * 
	 * @param playerId
	 * @param mailTeplateId
	 * @param params
	 * @param listMailAttach
	 */
	public void sendMailSigleToPlayer(int playerId, int mtid, Map<String, String> params, List<GainItemBean> attach) {
		asyncendMailToPlayerList(new Integer[] { playerId }, mtid, params, attach);
	}

	/**
	 * 生成mail id
	 * 
	 * @return
	 */
	public Long generateMailId() {
		return uuIdGenerator.nextId();
	}

	public int readMailById(PlayingRole playingRole, long mailId, S2CReadMail respMsg) {
		int playerId = playingRole.getId();
		Map<Long, HallMailBean> map = MailCache.getInstance().getMailByPlayerId(playerId);
		if (map == null || !map.containsKey(mailId)) {
			return ErrorCodeConstants.HALL_NO_MAIL;
		}
		HallMailBean mailBean = map.get(mailId);
		if (mailBean.getIsRead() > 0) {
			respMsg.mail_id = mailId;
			respMsg.is_read = (byte) (mailBean.getIsRead().intValue());
			return 1;
		}

		mailBean.setIsRead(2);
		List<GainItemBean> listMailAttach = mailBean.getAttachList();
		boolean isAttach = (listMailAttach != null && listMailAttach.size() > 0);
		if (isAttach) {
			mailBean.setIsRead(1);
		}
		MailDaoHelper.getInstance().asyncUpdateMailState(mailId, mailBean.getIsRead(), isAttach);
		respMsg.mail_id = mailId;
		respMsg.is_read = (byte) (mailBean.getIsRead().intValue());

		return 1;
	}

	/**
	 * 获取邮件的附件信息
	 * 
	 * @param playerId
	 * @param mailId
	 * @return 1.ok other errorcode
	 */
	public int gainMailById(PlayingRole playingRole, long mailId) {
		int playerId = playingRole.getId();
		Map<Long, HallMailBean> map = MailCache.getInstance().getMailByPlayerId(playerId);
		if (map == null || !map.containsKey(mailId)) {
			return ErrorCodeConstants.HALL_NO_MAIL;
		}
		HallMailBean mailBean = map.get(mailId);
		if (mailBean.getIsRead() == 2) { // 已领取
			return ErrorCodeConstants.HALL_MAIL_FINISH;
		}
		List<GainItemBean> listMailAttach = mailBean.getAttachList();
		boolean isAttach = (listMailAttach != null && listMailAttach.size() > 0);
		mailBean.setIsRead(2);
		MailDaoHelper.getInstance().asyncUpdateMailState(mailId, 2, isAttach);

		if (isAttach) {
			ItemManager.getInstance().gainItems(playingRole, listMailAttach);
		}

		return 1;
	}

	public void delMailById(int playerId, long[] mailIdList) {
		for (long mailId : mailIdList) {
			boolean isDel = MailCache.getInstance().removeMail(playerId, mailId);
			if (isDel) {
				MailDaoHelper.asyncRemoveMail(mailId);
			}
		}
	}

	/**
	 * 获取指定邮件后的列表
	 * 
	 * @param playerId
	 * @param lastMailId
	 * @return
	 */
	public MailInfo[] listMail(int playerId, long lastMailId) {
		Map<Long, HallMailBean> mapMail = MailCache.getInstance().getMailByPlayerId(playerId);
		List<MailInfo> listMailInfo = new ArrayList<>();
		if (mapMail == null || mapMail.size() <= 0) {
			return listMailInfo.toArray(new MailInfo[0]);
		}
		long remain_del_time = 1L;
		for (HallMailBean mail : mapMail.values()) {
			remain_del_time = mail.getCreateTime().getTime() + DEL_TIME_MIS - System.currentTimeMillis();
			remain_del_time = remain_del_time < 0 ? 0 : remain_del_time;
			if (remain_del_time <= 0) {
				mapMail.remove(mail.getId());
				continue;
			}
			if (mail.getId() <= lastMailId) {
				continue;
			}
			listMailInfo.add(packMailInfo(mail, remain_del_time));
		}
		return listMailInfo.toArray(new MailInfo[0]);
	}

	public MailInfo packMailInfo(HallMailBean mail, long remain_del_time) {
		MailInfo mailInfo = new MailInfo();
		mailInfo.mail_id = mail.getId();
		mailInfo.template_id = mail.getTemplateId();
		mailInfo.sendName = mail.getSendName();
		mailInfo.create_time = (int) (mail.getCreateTime().getTime() / 1000L);
		mailInfo.is_read = (byte) (mail.getIsRead().intValue());
		mailInfo.title = mail.getMailTitle();
		mailInfo.content = mail.getMailContent();
		mailInfo.remain_del_time = (int) (remain_del_time / 1000L);
		mailInfo.act_type = 0; // 0：无需操作，1.俱乐部邀请操作

		MailClubInfo clubInf = new MailClubInfo();
		if (StrKit.isNotEmpty(mail.getOtherMsg())) {
			JSONObject ob = JSON.parseObject(mail.getOtherMsg());
			if (ob != null) {
				mailInfo.act_type = ob.getIntValue("act_type");
				if (1 == mailInfo.act_type) {
					clubInf.club_id = ob.getIntValue("clubId");
					clubInf.club_name = ob.getString("clubName");
				}
			}
		}

		mailInfo.club_msg = clubInf;

		List<MailAttach> listAttach = new ArrayList<>();
		List<GainItemBean> listMailAttach = mail.getAttachList();
		if (listMailAttach != null && listMailAttach.size() > 0) {
			for (GainItemBean itemBean : listMailAttach) {
				MailAttach mailAttach = new MailAttach();
				mailAttach.cnt = itemBean.getCount();
				mailAttach.item_id = itemBean.getItemTemplateId();
				listAttach.add(mailAttach);
			}
		}

		mailInfo.attach = listAttach.toArray(new MailAttach[0]);
		return mailInfo;
	}

	/**
	 * 创建邮件
	 * 
	 * @param toPlayerId
	 * @param templateId
	 * @param sendName
	 * @param title
	 *            自行封装
	 * @param content
	 *            自行封装
	 * @param listMailAttach
	 *            自行封装邮件
	 */
	public void createMail(int toPlayerId, int templateId, String sendName, String title, String content, List<GainItemBean> listMailAttach, String otherMsg) {
		HallMailBean mailBean = new HallMailBean();
		mailBean.setCreateTime(new Date());
		mailBean.setDelFlag(0);
		mailBean.setId(generateMailId());
		mailBean.setIsRead(0);
		mailBean.setMailAttach(packMailAttachJson(listMailAttach));
		mailBean.setMailContent(content);
		mailBean.setMailTitle(title);
		mailBean.setPlayerId(toPlayerId);
		mailBean.setSendName(sendName);
		mailBean.setSendPlayerId(0);
		mailBean.setTemplateId(templateId);
		mailBean.setOtherMsg(otherMsg == null ? "" : otherMsg);

		MailCache.getInstance().addNew(toPlayerId, mailBean);
		MailDaoHelper.getInstance().asyncInsertMail(mailBean);
		// 推送新邮件到客户端
		PlayingRole pr = SessionManager.getInstance().getPlayer(toPlayerId);

		// 推送新邮件进客户端
		if (pr != null && pr.isChannelActive()) {
			S2CMailPushList respMsg = new S2CMailPushList();
			respMsg.mail_list = MailManager.getInstance().listMail(toPlayerId, mailBean.getId() - 1);
			pr.writeAndFlush(respMsg.build(pr.alloc()));
		}
	}

	public void addMail(int playerId, int templateId) {
		MailTemplate mt = MailTemplateCache.getInstance().getMailTemplateById(templateId);
		if (mt == null) {
			return;
		}
		createMail(playerId, templateId, "系统邮件", mt.getTitle(), mt.getWords(), preMailAttach(mt), null);
	}

	private String packMailAttachJson(List<GainItemBean> listMailAttach) {
		if (listMailAttach == null || listMailAttach.size() <= 0) {
			return "[]";
		}
		ObjectMapper mapper = new ObjectMapper();
		String jsonlist = "[]";
		try {
			jsonlist = mapper.writeValueAsString(listMailAttach);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return jsonlist;
	}

	private List<GainItemBean> preMailAttach(MailTemplate mailTemplate) {
		if (mailTemplate == null) {
			return null;
		}
		List<GainItemBean> listMailAttach = new ArrayList<>();
		packMailAttach(mailTemplate.getItem1(), mailTemplate.getNum1(), listMailAttach);
		packMailAttach(mailTemplate.getItem2(), mailTemplate.getNum2(), listMailAttach);
		packMailAttach(mailTemplate.getItem3(), mailTemplate.getNum3(), listMailAttach);
		packMailAttach(mailTemplate.getItem4(), mailTemplate.getNum4(), listMailAttach);
		packMailAttach(mailTemplate.getItem5(), mailTemplate.getNum5(), listMailAttach);
		return listMailAttach;
	}

	private void packMailAttach(int templateId, int num, List<GainItemBean> listMailAttach) {
		if (templateId <= 0 || num <= 0) {
			return;
		}

		GainItemBean gainItem = new GainItemBean();
		gainItem.setCount(num);
		gainItem.setItemTemplateId(templateId);
		listMailAttach.add(gainItem);
	}

	public static void main(String[] args) {
		Map<Integer, Integer> map = new ConcurrentHashMap<>();
		for (int i = 0; i < 20; i++) {
			map.put(i, i);
		}
		for (Map.Entry<Integer, Integer> key : map.entrySet()) {
			if (key.getKey() < 10) {
				map.remove(key.getKey());
			} else {
				map.put(key.getKey() * 100, 1);
			}
		}
		for (int key : map.keySet()) {
			System.out.println(key);
		}

		Map<String, String> pars = new HashMap<>();
		pars.put("$1", DateKit.formateDateToStr(new Date()));
		pars.put("$2", "XXX");
		pars.put("$3", ")))");
		String c = "$1$2向【$3】俱乐部捐献了5000金豆。$2";
		if (pars != null && pars.size() > 0) {
			for (String key : pars.keySet()) {
				c = c.replace(key, pars.get(key));
			}
		}
		System.out.println(c);
	}

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		long mis = System.currentTimeMillis() - DEL_TIME_MIS;
		Date date = new Date(mis);
		MailDao.getInstance().delPastDueMail(date);

	}
}
